using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Diagnostics;
using Lizk.WebScraper;
using System.Xml.Serialization;
using System.Reflection;

namespace TVScrapers
{
    public class TVComScraper : Scraper
    {
        private static LoginInformation settings = new LoginInformation();
        public static LoginInformation Settings
        {
            get { return settings; }
        }


        static TVComScraper()
        {
            LoadSettings();
        }

        public static void LoadSettings()
        {
            string settingsFile = Path.ChangeExtension(Assembly.GetExecutingAssembly().Location, ".xml");
            if (File.Exists(settingsFile))
            {
                try
                {
                    XmlSerializer mySerializer = new XmlSerializer(typeof(LoginInformation));
                    FileStream myFileStream = new FileStream(settingsFile, FileMode.Open);
                    settings = (LoginInformation)mySerializer.Deserialize(myFileStream);
                    myFileStream.Close();
                }
                catch
                {
                    SaveSettings(settingsFile);
                }
            }
            else
            {
                SaveSettings(settingsFile);
            }
        }

        private static void SaveSettings(string file) 
        {
            XmlSerializer mySerializer = new XmlSerializer(typeof(LoginInformation));
            // To write to a file, create a StreamWriter object.
            StreamWriter myWriter = new StreamWriter(file);
            mySerializer.Serialize(myWriter, settings);
            myWriter.Close();
        }


        public override ScraperResult[] Search(string search)
        {
            UpdateProgress(new ScraperEventArgs("Connecting to TV.com", ScraperEventArgs.ScaperStatus.Connecting));
            List<ScraperResult> results = new List<ScraperResult>();
            Uri uri = new Uri("http://www.tv.com/search.php?qs=" + Uri.EscapeUriString(search) + "&type=11&stype=all");
            ScraperResult sr = null;
            using (StreamReader s = new StreamReader(Connect(uri).GetResponseStream()))
            {
                UpdateProgress(new ScraperEventArgs("Connected to TV.com", ScraperEventArgs.ScaperStatus.Downloading));
                string line;
                while ((line = s.ReadLine()) != null)
                {
                    if (line.Contains("Show: "))
                    {
                        if (sr != null)
                            results.Add(sr);
                        int end = 0;
                        sr = new ScraperResult(Scrape(0, line, "/show/", "/summary", out end));
                        sr.Title = Scrape(end, line, "\">", "</a>");
                    }
                }
            }
            if (sr != null)
                results.Add(sr);
            UpdateProgress(new ScraperEventArgs("Search completed!", ScraperEventArgs.ScaperStatus.Done));
            SearchComplete(results);
            return results.ToArray();
        }

        private void GetSummary(ScraperResult sr)
        {
            UpdateProgress(new ScraperEventArgs("Getting title information", ScraperEventArgs.ScaperStatus.Connecting));

            Uri uri = new Uri("http://www.tv.com/show/" + Uri.EscapeUriString(sr.ID) + "/summary.html");

            using (StreamReader s = new StreamReader(Connect(uri).GetResponseStream()))
            {
                UpdateProgress(new ScraperEventArgs("Getting title information", ScraperEventArgs.ScaperStatus.Downloading));
                string line;
                while ((line = s.ReadLine()) != null)
                {
                    if (line.Contains("Premiered"))
                    {
                        line = s.ReadLine();
                        line = s.ReadLine();
                        try
                        {
                            DateTime t = DateTime.Parse(line);
                            sr.Year = t.Year;
                        }
                        catch
                        {
                        
                        }

                    }
                    if (line.Contains("content_headers"))
                    {
                        line = s.ReadLine();
                        while (!line.Contains("<h1>"))
                        {
                            line = s.ReadLine();
                        }
                        sr.Title = Scrape(0, line, "<h1>", "</h1>");
                    }
                    if (line.Contains("images/processed/thumb"))
                    {
                        string g = Scrape(0, line, "processed/thumb/", "\" alt=");
                        sr.ImageUrl = "http://image.com.com/tv/images/processed/photo_viewer/" + g;

                    }
                    if (line.Contains("summary_fold\" class=\"mt-10\">"))
                    {
                        line = s.ReadLine();
                        string tmp = "";
                        while (!line.Contains("<"))
                        {
                            tmp += line;
                            line = s.ReadLine();
                        }
                        sr.Summary = ClearHTML(br2nl(Regex.Replace(tmp, @"\s+", @" ").Trim())); // Scrape(0, tmp, ">", "<");
                    }


                    if (line.Contains("Show Categories:")) 
                    {
                        int a = 0;
                        line = s.ReadLine();
                        string st = line;
                        while (st.Contains("genre")) 
                        {
                            sr.Genres.Add(Scrape(0, st, "\">", "</a>", out a).Trim());
                            st = st.Substring(a);
                        }
                    }


                }
            }
            UpdateProgress(new ScraperEventArgs("Information downloaded!", ScraperEventArgs.ScaperStatus.Done));

        }

        private void GetEpisodes(ScraperResult sr)
        {
            UpdateProgress(new ScraperEventArgs("Getting episode information", ScraperEventArgs.ScaperStatus.Connecting));
            Uri uri = new Uri("http://www.tv.com/show/" + Uri.EscapeUriString(sr.ID) + "/episode_listings.html?season=0");
            using (StreamReader s = new StreamReader(Connect(uri).GetResponseStream()))
            {
                UpdateProgress(new ScraperEventArgs("Getting episode information", ScraperEventArgs.ScaperStatus.Downloading));
                string line;
                Episode episode = null;
                while ((line = s.ReadLine()) != null)
                {
                    if (line.Contains("summary.html?tag=ep_list;title"))
                    {
                        if (episode != null)
                            sr.Episodes.Add(episode);
                        episode = new Episode(Scrape(0, line, "\">", "</a>"));
                        line = s.ReadLine();
                        line = s.ReadLine();
                        line = s.ReadLine();
                        try
                        {
                            DateTime dt = DateTime.Parse(line, new CultureInfo("en-US", false).DateTimeFormat);
                            episode.AirDate = dt;
                        }catch{}
                        line = s.ReadLine();
                        line = s.ReadLine();
                        line = s.ReadLine();
                        episode.ID = line.Trim();
                    }
                }
                if (episode != null)
                    sr.Episodes.Add(episode);
            }
            UpdateProgress(new ScraperEventArgs("Episode info downloaded!", ScraperEventArgs.ScaperStatus.Done));

                
        }
        
        private void Login()
        {
            UpdateProgress(new ScraperEventArgs("Logging into TV.com", ScraperEventArgs.ScaperStatus.Connecting));
            Connect(new Uri("http://authorize.tv.com/1324-4-90.html?tag=login;login&EMAILADDR=" + Uri.EscapeUriString(Settings.Username) + "&PASSWORD=" + Uri.EscapeUriString(Settings.Password))).Close();
        }


        private void GetEpisodeInfo(ScraperResult sr)
        {
            UpdateProgress(new ScraperEventArgs("Getting episode information", ScraperEventArgs.ScaperStatus.Connecting));
            Regex season = new Regex(@"(\d+)\s+-\s+(\d+)");
            Uri uri = new Uri("http://www.tv.com/show/" + Uri.EscapeUriString(sr.ID) + "/episode_guide.html?printable=1");
            Episode episode = null;
            using (StreamReader s = new StreamReader(Connect(uri).GetResponseStream()))
            {
                string line;
                while ((line = s.ReadLine()) != null)
                {
                    if (line.Contains("<h1>"))
                    {
                        if(episode != null)
                            sr.Episodes.Add(episode);
                        episode = new Episode("");
                        line = s.ReadLine();
                        Match m = season.Match(line);
                        if (m.Success)
                        {
                            episode.Season = Convert.ToInt32(m.Groups[1].Value);
                            episode.EpisodeNumber = Convert.ToInt32(m.Groups[2].Value);
                        }
                        string title = "";
                        line = s.ReadLine();
                        while (!line.Contains("</a>"))
                        {
                            title += line;
                            line = s.ReadLine();
                        }
                        episode.Title = title.Trim();
                    }
                    if (line.Contains("<p>"))
                    {
                        if (episode != null)
                            episode.Summary = ClearHTML(br2nl(Scrape(0, line, "<p>", "</p>")));
                    }
                    if (line.Contains("First aired:"))
                    {
                        if (episode != null)
                            try
                            {
                                DateTime dt = DateTime.Parse(Scrape(0, line, "</span> ", "<br/>"), new CultureInfo("en-US", false).DateTimeFormat);
                                episode.AirDate = dt;
                            }
                            catch { }
                        
                    }
                }
            }
            if (episode != null)
                sr.Episodes.Add(episode);
            UpdateProgress(new ScraperEventArgs("Episode summary downloaded!", ScraperEventArgs.ScaperStatus.Done));

        }

        public override ScraperResult GetTitleInfo(string id)
        {
            ScraperResult sr = new ScraperResult(id);

            Login();
            GetSummary(sr);
            GetEpisodeInfo(sr);
            ScrapeComplete(sr);
            return sr;
        }

        [XmlRoot]
        public class LoginInformation
        {
            private string username;
            private string password;

            public string Password
            {
                get { return password; }
                set { password = value; }
            }

            public string Username
            {
                get { return username; }
                set { username = value; }
            }
            public LoginInformation()
            {
                this.username = "username";
                this.password = "password";
            }

        }

    }


    

}
